<template>
	<div class="p-0">
		<n-grid x-gap="12">
			<n-gi span="8">
				<n-card>
					<template #header>
						<n-space>
							<n-button @click="initMenuList" type="primary">
								<template #icon>
									<n-icon :component="reloadIcon"></n-icon>
								</template>
								刷新
							</n-button>
							<n-button type="primary" ghost @click="expandAll = !expandAll">
								<template #icon>
									<n-icon :component="upIcon" v-if="expandAll"></n-icon>
									<n-icon :component="downIcon" v-else></n-icon>
								</template>
								{{ expandAll ? "收起全部" : "展开全部" }}
							</n-button>
						</n-space>
					</template>
					<n-spin :show="listLoading">
						<n-tree
							block-line
							:data="data"
							selectable
							:default-expand-all="expandAll"
						/>
					</n-spin>
				</n-card>
			</n-gi>
			<n-gi span="16">
				<n-card>
					<template #header>
						<div class="flex justify-between">
							<div>
								<div class="flex items-center" v-if="editData">
									<n-icon :component="editIcon" class="mr-2"></n-icon>
									编辑菜单 : {{ editData.label }}
								</div>
								<div class="flex items-center" v-else>
									<n-icon :component="addIcon" class="mr-2"></n-icon>
									新增菜单
								</div>
							</div>
							<div>
								<n-button @click="resetForm" type="primary" v-if="editData">
									<template #icon>
										<n-icon :component="addIcon"></n-icon>
									</template>
									新增菜单
								</n-button>
							</div>
						</div>
					</template>
					
					<n-form
						class="mt-5"
						ref="formRef"
						:model="formValue"
						:rules="rules"
						label-placement="left"
						label-width="80"
						require-mark-placement="right-hanging"
					>
						<n-form-item label="父级" path="parent_id">
							<n-tree-select
								v-model:value="formValue.parent_id"
								:options="parentOptions"
								label-field="label"
								key-field="id"
								children-field="children"
							/>
						</n-form-item>
						<n-form-item label="名称" path="label">
							<n-input v-model:value="formValue.label" placeholder="请输入菜单名称" />
						</n-form-item>
						<n-form-item label="图标" path="icon">
							<icon-select v-model:value="formValue.icon"
							             v-model:library="formValue.icon_library"></icon-select>
						</n-form-item>
						<n-form-item label="类型">
							<n-radio-group v-model:value="menuType" name="menu_type">
								<n-radio-button value="router" label="菜单" />
								<n-radio-button value="href" label="链接" />
							</n-radio-group>
						</n-form-item>
						<n-form-item label="路由" path="router" v-if="menuType == 'router'">
							<n-input v-model:value="formValue.router" placeholder="请输入菜单路由" />
						</n-form-item>
						<n-form-item label="链接" path="href" v-if="menuType == 'href'">
							<n-input v-model:value="formValue.href" placeholder="请输入菜单链接" />
						</n-form-item>
						<n-form-item label="文件路径" path="path">
							<n-input v-model:value="formValue.path" placeholder="请输入文件路径, 如: /dashboard" />
						</n-form-item>
						<n-form-item label="标识符" path="key">
							<n-input v-model:value="formValue.key" placeholder="请输入标识符" />
						</n-form-item>
						<n-form-item label="排序" path="order">
							<n-input-number v-model:value="formValue.order" min="0" max="99999999" />
						</n-form-item>
						<n-form-item label="显示" path="show">
							<n-switch v-model:value="formValue.show"
							          :checked-value="1"
							          :unchecked-value="0"
							/>
						</n-form-item>
						<n-form-item label="api权限" path="api">
							<n-tree-select
								show-path
								multiple
								cascade
								checkable
								check-strategy="child"
								:options="apiOptions"
								v-model:value="formValue.apis"
							/>
						</n-form-item>
					</n-form>
					
					<template #footer>
						<n-space class="justify-end">
							<n-button type="primary" @click="submit">提 交</n-button>
						</n-space>
					</template>
				</n-card>
			</n-gi>
		</n-grid>
	</div>
</template>

<script lang="ts" setup>
import {h, ref} from "vue"
import {NButton, NIcon, NPopconfirm, useMessage} from "naive-ui"
import {carbonIcon, ionicons5Icon} from "@/utils/icon"
import IconSelect from "@/components/slow/icon-select.vue"
import {systemMenu as request} from "@/api/api"
import {deepClone} from "@/utils/tools"

const addIcon = ionicons5Icon("Add")
const upIcon = ionicons5Icon("ChevronUpOutline")
const downIcon = ionicons5Icon("ChevronDownOutline")
const editIcon = carbonIcon("Edit")
const checkIcon = ionicons5Icon("CheckmarkSharp")
const removeIcon = carbonIcon("TrashCan")
const reloadIcon = ionicons5Icon("ReloadOutline")

const message = useMessage()

const expandAll = ref(false)

const treeDataHandler = (data: any[]) => {
	return data.map((item: any) => {
		if (item.children) {
			item.children = treeDataHandler(item.children)
		}
		
		if (item.icon) {
			// 渲染图标
			item.prefix = () => h(NIcon, {
				component: item.icon_library == "carbon" ? carbonIcon(item.icon) : ionicons5Icon(item.icon),
				size: 16,
			})
		}
		
		item.suffix = () => [
			h(
				NButton,
				{class: "mr-2", text: true, type: "primary", onclick: () => edit(item)},
				{default: () => h(NIcon, {component: editIcon, size: 16})},
			),
			h(
				NPopconfirm,
				{
					onPositiveClick: () => remove(item),
				},
				{
					trigger: () => h(
						NButton,
						{class: "mr-2", text: true, type: "error"},
						{default: () => h(NIcon, {component: removeIcon, size: 16})},
					),
					default: () => "确认删除?",
				},
			),
		]
		return item
	})
}

const listLoading = ref(false)
const data: any = ref([])
const parentOptions: any = ref([])

const initMenuList = () => {
	listLoading.value = true
	request.list().then((res: any) => {
		res.data = res.data ? res.data : []
		data.value = treeDataHandler(deepClone(res.data))
		
		res.data.unshift({
			id: 0,
			label: "顶级",
		})
		parentOptions.value = res.data
		
		listLoading.value = false
	})
}

initMenuList()

const apiOptions = ref([])

const getApiOptions = () => {
	request.apis().then((res: any) => {
		apiOptions.value = res.data
	})
}

getApiOptions()

// 菜单类型
const menuType = ref("router")
const editData = ref()
const formRef = ref()

const formValue = ref({
	parent_id: 0,
	order: 0,
	label: "",
	router: "",
	href: "",
	path: "",
	key: "",
	icon: "",
	icon_library: "",
	show: 1,
	apis: <any>[],
})

const rules = {
	label: {
		required: true,
		message: "请输入菜单名称",
		trigger: ["blur"],
	},
	key: {
		required: true,
		message: "请输入标识符",
		trigger: ["blur"],
	},
}

const resetForm = () => {
	formValue.value = {
		parent_id: 0,
		order: 0,
		label: "",
		router: "",
		href: "",
		path: "",
		key: "",
		icon: "",
		icon_library: "",
		show: 1,
		apis: [],
	}
	
	menuType.value = "router"
	editData.value = null
	initMenuList()
}

const edit = (value: any) => {
	let apis = []
	for (let item of value.apis) {
		if (item) {
			apis.push(item.id + "")
		}
	}
	
	formValue.value = {
		parent_id: value.parent_id,
		order: value.order,
		label: value.label,
		router: value.router,
		href: value.href,
		path: value.path,
		key: value.key,
		icon: value.icon,
		icon_library: value.icon_library,
		show: value.show,
		apis: apis,
	}
	
	editData.value = deepClone(value)
}

// 删除
const remove = (value: any) => {
	request.delete(value.id).then((res: any) => {
		if (res.code == 200) {
			message.success(res.message)
			initMenuList()
			resetForm()
		} else {
			message.error(res.message)
		}
	})
}


const submit = (e: MouseEvent) => {
	e.preventDefault()
	formRef.value?.validate((errors: unknown) => {
		if (!errors) {
			if (editData.value) {
				let data: any = formValue.value
				data.id = editData.value.id
				
				request.update(data).then((res: any) => {
					if (res.code == 200) {
						message.success(res.message)
						resetForm()
					} else {
						message.error(res.message)
					}
				})
			} else {
				request.store(formValue.value).then((res: any) => {
					if (res.code == 200) {
						message.success(res.message)
						resetForm()
					} else {
						message.error(res.message)
					}
				})
			}
		}
	})
}
</script>

<style>
.n-tree .n-tree-node {
	padding: 6px 2px;
}
</style>
